/******************************************************************************
 * * cale_proc.c - implementation of calendar key and event handler
 *
 * *(C) Copyright 2019 Asr International Ltd.
 * * All Rights Reserved
 * ******************************************************************************/
#include "cale_global.h"

/**
 * Process user key of Calendar UI
 */
UINT8 Cale_Key_Proc_Calendar(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
        {
            Nav_Back(ACT_ID_ANY);
            return(1);
        }

        case KEY_OK:
        case KEY_SOFTLEFT:
        {
            Display_Calendar_Option();
            return(1);
        }

        case KEY_END:
        {
            Nav_Home(ACT_ID_ANY);
            return(1);
        }

        case KEY_UP:
        case KEY_DOWN:
        case KEY_LEFT:
        case KEY_RIGHT:
        {
            // udpate weeks
            Hal_Mem_Copy(&(g_CalendarMng.DayOnShow),
                         lv_calendar_get_showed_date(obj),
                         sizeof(lv_calendar_date_t));

            return(1);
        }

        default:
            break;
        } /* switch */
    }

    return(1);
} /* Cale_Key_Proc_Calendar */

/**
 * Process user key of Calendar option UI
 */
UINT8 Cale_Key_Proc_Cale_Opt(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            return(1);

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            return(1);

        case KEY_OK:
        case KEY_UP:
        case KEY_DOWN:
            return(0);

        default:
            break;
        }     /* switch */
    }

    return(1);
}

/**
 * Process user key of Calendar option UI
 */
UINT8 Cale_Key_Proc_Go_To_Date(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    UI_Normal_Date_Desc_t *pTmpDesc                = NULL;
    INT8                  Buf[5] = {0};

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            return(1);

        case KEY_OK:
        {
            pTmpDesc = (UI_Normal_Date_Desc_t *)g_CalendarMng.CurrentDesc;

            // Get latest selected year
            lv_roller_get_selected_str(pTmpDesc->ContDate.RollerYear.Roller, Buf,0);
            if (NULL == g_CalendarMng.LunarDate)
            {
                g_CalendarMng.DayOnShow.year = atoi(Buf);
                lv_roller_get_selected_str(pTmpDesc->ContDate.RollerMonth.Roller, Buf,0);
                g_CalendarMng.DayOnShow.month = atoi(Buf);
                lv_roller_get_selected_str(pTmpDesc->ContDate.RollerDay.Roller, Buf,0);
                g_CalendarMng.DayOnShow.day = atoi(Buf);

                UI_Calendar_Only_Desc_t *Des = Nav_Get_Param(ACT_ID_CALENDAR);
                Hal_Mem_Copy(&Des->Calendar.ShowedDate,
                             &g_CalendarMng.DayOnShow,
                             sizeof(lv_calendar_date_t));
                Nav_Forward(ACT_ID_ANY, ACT_ID_CALENDAR, NULL, NULL);
            }
            else
            {
                g_CalendarMng.LunarDate->year = atoi(Buf);
                lv_roller_get_selected_str(pTmpDesc->ContDate.RollerMonth.Roller, Buf,0);
                g_CalendarMng.LunarDate->month = atoi(Buf);
                lv_roller_get_selected_str(pTmpDesc->ContDate.RollerDay.Roller, Buf,0);
                g_CalendarMng.LunarDate->day = atoi(Buf);
                Nav_Forward(ACT_ID_ANY, ACT_ID_CALENDAR_LUNAR_CALE, NULL, NULL);
            }
            return(1);
        }

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            return(1);

        case KEY_LEFT:
        case KEY_RIGHT:
        case KEY_UP:
        case KEY_DOWN:
            return(0);

        default:
            break;
        }     /* switch */
    }

    return(0);
}

/**
 * Process user key of Calendar add reminder UI
 */
UINT8 Cale_Key_Proc_Add_Reminder(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    UI_Normal_NoTitle_Label_Ta_Desc_t *pTmpDesc;
    const INT8                        *TaTxt;
    UINT8                             TaTxtLen;
    UINT8                             ReminderCnt;
    UI_Reminder_t                     *Reminder;

    pTmpDesc = (UI_Normal_NoTitle_Label_Ta_Desc_t *)g_CalendarMng.CurrentDesc;

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
        {
            if (g_CalendarMng.ReminderTxtLeft == UI_CALENDAR_MAX_REMINDER_INPUT_LEFT)
            {
                Nav_Back(ACT_ID_ANY);
                return(1);
            }
            else
            {
                UI_Cale_Input_Handler(0);
            }
            break;
        }

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            return(1);

        case KEY_OK:
        {
            if (NULL == g_CalendarMng.ReminderInOper)
            {       // for add reminder
                ReminderCnt = 0;
                Reminder = _lv_ll_get_head(&g_CalendarMng.Reminder);
                while (Reminder)
                {
                    ReminderCnt++;
                    Reminder = _lv_ll_get_next(&g_CalendarMng.Reminder, Reminder);
                }
                if (NV_CALENDAR_MAX_REMINDER_NUM == ReminderCnt)
                {
                    UI_Log_Out(UI_SUB_MODULE_CALENDAR, UI_LOG_LEVEL_WARNING, "memory full\n");
                    Display_Calendar_Add_Reminder_Memory_Full();
                    return(1);
                }
                g_CalendarMng.ReminderInOper = (UI_Reminder_t *)Hal_Mem_Alloc(sizeof(UI_Reminder_t));
            }
            Hal_Mem_Set(g_CalendarMng.ReminderInOper, 0, sizeof(UI_Reminder_t));

            // save reminder txt
            TaTxt    = lv_textarea_get_text(pTmpDesc->ContTa.TextArea);
            TaTxtLen = strlen(TaTxt);
            if (0 == TaTxtLen)
            {
                TaTxt = lv_lang_get_text(PHONE_TEXT_ID_REMINDER);
            }
            snprintf(g_CalendarMng.ReminderInOper->Info.Text,
                     NV_CALENDAR_MAX_REMINDER_LEN, "%s", (INT8 *)TaTxt);

            Display_Calendar_Set_Alarm();
            return(1);
        }

        case KEY_0:
        case KEY_1:
        case KEY_2:
        case KEY_3:
        case KEY_4:
        case KEY_5:
        case KEY_6:
        case KEY_7:
        case KEY_8:
        case KEY_9:
        case KEY_ASTERISK:
            if (0 < g_CalendarMng.ReminderTxtLeft)
            {
                UI_Cale_Input_Handler(1);
            }
            else
            {
                return(1);
            }
            break;

        case KEY_SOFTLEFT:
        case KEY_DIAL:
            return(1);

        default:
            break;
        }     /* switch */
    }
    else if(KEY_LONGPRESS == Key_Sta)
    {
        if(KEY_SOFTRIGHT == Key_Val)
        {
            g_CalendarMng.ReminderTxtLeft = UI_CALENDAR_MAX_REMINDER_INPUT_LEFT;
            lv_textarea_set_text(pTmpDesc->ContTa.TextArea, "");
            return(1);
        }
    }

    return(0);
}     /* Cale_Key_Proc_Add_Reminder */

/**
 * Process user key of Calendar view edit UI
 */
UINT8 Cale_Key_Proc_View_Edit(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    UI_Normal_NoTitle_Label_Ta_Desc_t *pTmpDesc;
    const INT8                        *TaTxt;
    UINT8                             TaTxtLen;

    pTmpDesc = (UI_Normal_NoTitle_Label_Ta_Desc_t *)g_CalendarMng.CurrentDesc;

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
        {
            if (g_CalendarMng.ReminderTxtLeft == UI_CALENDAR_MAX_REMINDER_INPUT_LEFT)
            {
                Nav_Back(ACT_ID_ANY);
                return(1);
            }
            else
            {
                UI_Cale_Input_Handler(0);
            }
            break;
        }

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            return(1);

        case KEY_OK:
        {
            TaTxt    = lv_textarea_get_text(pTmpDesc->ContTa.TextArea);
            TaTxtLen = strlen(TaTxt);
            if (0 == TaTxtLen)
            {
                TaTxt = lv_lang_get_text(PHONE_TEXT_ID_REMINDER);
                TaTxtLen = strlen(TaTxt);
            }
            g_CalendarMng.EditTxt = (INT8 *)Hal_Mem_Alloc(TaTxtLen + 1);
            Hal_Mem_Copy(g_CalendarMng.EditTxt, TaTxt, TaTxtLen + 1);

            Display_Calendar_Set_Alarm();
            return(1);
        }

        case KEY_0:
        case KEY_1:
        case KEY_2:
        case KEY_3:
        case KEY_4:
        case KEY_5:
        case KEY_6:
        case KEY_7:
        case KEY_8:
        case KEY_9:
        case KEY_ASTERISK:
            if (0 < g_CalendarMng.ReminderTxtLeft)
            {
                UI_Cale_Input_Handler(1);
            }
            else
            {
                return(1);
            }
            break;

        case KEY_SOFTLEFT:
        case KEY_DIAL:
            return(1);

        default:
            break;
        }     /* switch */
    }
    else if(KEY_LONGPRESS == Key_Sta)
    {
        if(KEY_SOFTRIGHT == Key_Val)
        {
            g_CalendarMng.ReminderTxtLeft = UI_CALENDAR_MAX_REMINDER_INPUT_LEFT;
            lv_textarea_set_text(pTmpDesc->ContTa.TextArea, "");
            return(1);
        }
    }

    return(0);
}

/**
 * Process user key of Calendar Set Alarm UI
 */
UINT8 Cale_Key_Proc_Set_Alarm(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            return(1);

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            return(1);

        case KEY_OK:
        case KEY_UP:
        case KEY_DOWN:
            return(0);            

        default:
            break;
        }     /* switch */
    }

    return(1);
}

/**
 * Process user key of Calendar Set Time UI
 */
UINT8 Cale_Key_Proc_Set_Time(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    UI_Normal_Time_Desc_t *pTmpDesc;
    hal_rtc_t             RtcTime;
    UINT8                 Hour;
    UINT8                 Min;
    INT8                  Buf[5] = {0};
    BOOL                  AddAlarm;

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            return(1);

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            return(1);

        case KEY_OK:
        {
            pTmpDesc = (UI_Normal_Time_Desc_t *)g_CalendarMng.CurrentDesc;
            lv_roller_get_selected_str(pTmpDesc->ContTime.Roller1.Roller, Buf,0);
            Hour = atoi(Buf);
            lv_roller_get_selected_str(pTmpDesc->ContTime.Roller2.Roller, Buf,0);
            Min = atoi(Buf);

            Hal_Rtc_Gettime(&RtcTime);

            AddAlarm = FALSE;
            if (UI_CALE_PROCESS_ADD_REMINDER == g_CalendarMng.Process)
            {
                if (RtcTime.tm_year < g_CalendarMng.DayOnShow.year)
                {
                    AddAlarm = TRUE;
                }
                else if (RtcTime.tm_year == g_CalendarMng.DayOnShow.year)
                {
                    if (RtcTime.tm_mon < g_CalendarMng.DayOnShow.month)
                    {
                        AddAlarm = TRUE;
                    }
                    else if (RtcTime.tm_mon == g_CalendarMng.DayOnShow.month)
                    {
                        if (RtcTime.tm_mday < g_CalendarMng.DayOnShow.day)
                        {
                            AddAlarm = TRUE;
                        }
                        else if (RtcTime.tm_mday == g_CalendarMng.DayOnShow.day)
                        {
                            if ((RtcTime.tm_hour < Hour)
                                || ((RtcTime.tm_hour == Hour)
                                    && (RtcTime.tm_min < Min)))
                            {
                                AddAlarm = TRUE;
                            }
                        }
                    }
                }
            }
            else // edit
            {
                if ((RtcTime.tm_year == g_CalendarMng.ReminderInOper->Info.Year)
                    && (RtcTime.tm_mon == g_CalendarMng.ReminderInOper->Info.Mon)
                    && (RtcTime.tm_mday == g_CalendarMng.ReminderInOper->Info.Day))
                {
                    if ((RtcTime.tm_hour < Hour)
                        || ((RtcTime.tm_hour == Hour)
                            && (RtcTime.tm_min < Min)))
                    {
                        AddAlarm = TRUE;
                    }
                }
                else
                {
                    AddAlarm = TRUE;
                }
            }

            if (TRUE == AddAlarm)
            {
                if (UI_CALE_PROCESS_ADD_REMINDER == g_CalendarMng.Process)
                {
                    UI_Cale_Save_For_Add_Reminder(Hour, Min);
                }
                else
                {/*View all or view today process*/
                    UI_Cale_Save_For_Edit_Reminder(Hour, Min);
                }
                Display_Calendar_Reminder_Added();
            }
            else
            {
                Display_Calendar_Date_Past();
            }
            return(1);
        }

        case KEY_LEFT:
        case KEY_RIGHT:
        case KEY_UP:
        case KEY_DOWN:
            return(0);

        default:
            break;
        }     /* switch */
    }

    return(0);
} /* Cale_Key_Proc_Set_Time */

/**
 * Process user key of Calendar Set Date UI
 */
UINT8 Cale_Key_Proc_Set_Date(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    UI_Normal_Date_Desc_t *pTmpDesc;
    hal_rtc_t             RtcTime, SetTime;
    INT8                  Buf[3] = {0};
    BOOL                  AddAlarm;

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            return(1);

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            return(1);

        case KEY_OK:
        {
            pTmpDesc = (UI_Normal_Date_Desc_t *)g_CalendarMng.CurrentDesc;

            // Get the current time
            Hal_Rtc_Gettime(&RtcTime);

            lv_roller_get_selected_str(pTmpDesc->ContDate.RollerYear.Roller, Buf,0);
            SetTime.tm_year = atoi(Buf);
            lv_roller_get_selected_str(pTmpDesc->ContDate.RollerMonth.Roller, Buf,0);
            SetTime.tm_mon = atoi(Buf);
            lv_roller_get_selected_str(pTmpDesc->ContDate.RollerDay.Roller, Buf,0);
            SetTime.tm_mday = atoi(Buf);

            AddAlarm = FALSE;
            if (RtcTime.tm_year < SetTime.tm_year)
            {
                AddAlarm = TRUE;
            }
            else if (RtcTime.tm_year == SetTime.tm_year)
            {
                if (RtcTime.tm_mon < SetTime.tm_mon)
                {
                    AddAlarm = TRUE;
                }
                else if (RtcTime.tm_mon == SetTime.tm_mon)
                {
                    if (RtcTime.tm_mday <= SetTime.tm_mday)
                    {
                        AddAlarm = TRUE;
                    }
                }
            }
            if (AddAlarm)
            {
                g_CalendarMng.ReminderInOper->Info.Year = SetTime.tm_year;
                g_CalendarMng.ReminderInOper->Info.Mon  = SetTime.tm_mon;
                g_CalendarMng.ReminderInOper->Info.Day  = SetTime.tm_mday;

                Display_Calendar_Set_Time();
            }
            else
            {
                Display_Calendar_Date_Past();
            }
            return(1);
        }

        case KEY_LEFT:
        case KEY_RIGHT:
        case KEY_UP:
        case KEY_DOWN:
            return(0);            

        default:
            break;
        }     /* switch */
    }

    return(0);
} /* Cale_Key_Proc_Set_Date */

#if 0
/**
 * Process user key of Calendar view today
 */
UINT8 Cale_Key_Proc_View_Today(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            return(1);

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            return(1);

        case KEY_SOFTLEFT:
        case KEY_OK:
            Display_Calendar_View_Option();
            return(1);

        case KEY_UP:
        case KEY_DOWN:
        case KEY_LEFT:
        case KEY_RIGHT:
        {
            if ((KEY_UP == Key_Val) || (KEY_LEFT == Key_Val))
            {
                g_CalendarMng.ReminderInOper
                    = UI_Cale_Get_Prev_Reminder(g_CalendarMng.ReminderInOper, TRUE);
            }
            else
            {
                g_CalendarMng.ReminderInOper
                    = UI_Cale_Get_Next_Reminder(g_CalendarMng.ReminderInOper, TRUE);
            }
            UI_Cale_Display_Reminder((UI_Normal_Reminder_Desc_t *)g_CalendarMng.CurrentDesc,
                                     g_CalendarMng.ReminderInOper,
                                     TRUE);
            return(1);
        }

        default:
            break;
        }     /* switch */
    }

    return(1);
} /* Cale_Key_Proc_View_Today */
#endif

/**
 * Process user key of Calendar view option
 */
UINT8 Cale_Key_Proc_Cale_View_Opt(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            return(1);

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            return(1);

        case KEY_OK:
        case KEY_UP:
        case KEY_DOWN:
            return(0);            

        default:
            break;
        }     /* switch */
    }

    return(1);
}

/**
 * Process user key of Calendar Add Reminder Memory Full UI
 */
UINT8 Cale_Key_Proc_Add_Reminder_Mem_Full(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            return(1);

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            return(1);

        case KEY_OK:
            Nav_Back(ACT_ID_ANY);
            Display_Calendar_View_All();
            return(1);

        default:
            break;
        }     /* switch */
    }

    return(1);
}

/**
 * Process user key of Calendar Delete
 */
UINT8 Cale_Key_Proc_Cale_Delete(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            return(1);

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            return(1);

        case KEY_OK:
            UI_Cale_Delete_Reminder();
            Display_Calendar_Reminder_Deleted();
            return(1);

        default:
            break;
        }     /* switch */
    }

    return(1);
}

/**
 * Process user key of Calendar View All
 */
UINT8 Cale_Key_Proc_View_All(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    BOOL IsViewToday = FALSE;

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTLEFT:
            if (UI_CALE_PROCESS_ADD_REMINDER != g_CalendarMng.Process)
            {
                Display_Calendar_View_Edit();
            }
            return(1);

        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            return(1);

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            return(1);

        case KEY_OK:
            Display_Calendar_Delete();
            return(1);

        case KEY_UP:
        case KEY_DOWN:
        case KEY_LEFT:
        case KEY_RIGHT:
        {
            if (UI_CALE_PROCESS_VIEW_TODAY == g_CalendarMng.Process)
            {
                IsViewToday = TRUE;
            }
            if ((KEY_UP == Key_Val) || (KEY_LEFT == Key_Val))
            {
                g_CalendarMng.ReminderInOper
                    = UI_Cale_Get_Prev_Reminder(g_CalendarMng.ReminderInOper, IsViewToday);
            }
            else
            {
                g_CalendarMng.ReminderInOper
                    = UI_Cale_Get_Next_Reminder(g_CalendarMng.ReminderInOper, IsViewToday);
            }
            UI_Cale_Display_Reminder((UI_Normal_Reminder_Desc_t *)g_CalendarMng.CurrentDesc,
                                     g_CalendarMng.ReminderInOper,
                                     IsViewToday);

            return(1);
        }

        default:
            break;
        }     /* switch */
    }

    return(1);
}

/**
 * Process user key of Calendar Memory Full UI
 */
UINT8 Cale_Key_Proc_Reminder_Alarm_Ring(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    If_Setting_Play_Tone_t    *PlayToneReq;
    UI_Reminder_t             *Reminder;
    UI_Reminder_t             *ReminderTmp;
    UINT32                    ReminderSnd;
    hal_rtc_t                 RtcTime;
    NV_UI_Calendar_Reminder_t NvReminderInfo;

    if ((KEY_RELEASED == Key_Sta)
        && ((KEY_SOFTRIGHT == Key_Val)
            || (KEY_OK == Key_Val)))
    {
        if (g_CalendarMng.RingTimer)
        {
            Hal_Timer_Stop(g_CalendarMng.RingTimer);
            g_CalendarMng.RingTimer = NULL;

            printf("%s: stop timer and tone\n", __FUNCTION__);

            PlayToneReq = (If_Setting_Play_Tone_t *)Hal_Mem_Alloc(sizeof(If_Setting_Play_Tone_t));
            PlayToneReq->PlayCtrl = IF_SETTING_PLAY_TONS_STOP;
            PlayToneReq->ToneType = IF_SETTING_TONS_TYPE_CALENDAR;
            Setting_Play_Tone_Req(PlayToneReq);
        }

        // record the next reminder with the same alarm time
        ReminderTmp = g_CalendarMng.RingReminder;
        g_CalendarMng.RingReminder = _lv_ll_get_next(&g_CalendarMng.Reminder,
                                                    g_CalendarMng.RingReminder);
        if (g_CalendarMng.RingReminder)
        {
            printf("%s: %d/%d/%d,%d:%d,%s\n", __FUNCTION__,
                   g_CalendarMng.RingReminder->Info.Year,g_CalendarMng.RingReminder->Info.Mon,
                   g_CalendarMng.RingReminder->Info.Day,g_CalendarMng.RingReminder->Info.Hour,
                   g_CalendarMng.RingReminder->Info.Min,g_CalendarMng.RingReminder->Info.Text);
            if (0 != UI_Cale_Compare_Reminder_Time(&ReminderTmp->Info,
                                                   &g_CalendarMng.RingReminder->Info))
            {
                g_CalendarMng.RingReminder = NULL;
            }
        }

        if (KEY_SOFTRIGHT != Key_Val) // postponed
        {
            // delay for 10 minutes
            RtcTime.tm_year = ReminderTmp->Info.Year;
            RtcTime.tm_mon  = ReminderTmp->Info.Mon;
            RtcTime.tm_mday = ReminderTmp->Info.Day;
            RtcTime.tm_hour = ReminderTmp->Info.Hour;
            RtcTime.tm_min  = ReminderTmp->Info.Min;
            RtcTime.tm_sec  = 0;
            RtcTime.tm_wday = ReminderTmp->Info.Wday;
            ReminderSnd = UI_Time_to_Seconds(&RtcTime);
            // ReminderSnd  = UI_Get_Timestamp_In_Second();
            ReminderSnd += 10 * 60;   // add 10 min

            UI_Seconds_to_Time(ReminderSnd, &RtcTime);

            ReminderTmp->Info.Year = RtcTime.tm_year;
            ReminderTmp->Info.Mon  = RtcTime.tm_mon;
            ReminderTmp->Info.Day  = RtcTime.tm_mday;
            ReminderTmp->Info.Wday = RtcTime.tm_wday;
            ReminderTmp->Info.Hour = RtcTime.tm_hour;
            ReminderTmp->Info.Min  = RtcTime.tm_min;

            Reminder = _lv_ll_get_next(&g_CalendarMng.Reminder, ReminderTmp);
            while (Reminder)
            {
                if (0 > UI_Cale_Compare_Reminder_Time(&ReminderTmp->Info, &Reminder->Info))
                {
                    break;
                }
                Reminder = _lv_ll_get_next(&g_CalendarMng.Reminder, Reminder);
            }
            _lv_ll_move_before(&g_CalendarMng.Reminder, ReminderTmp, Reminder);

            // write nvram
            Hal_Mem_Copy(&NvReminderInfo, &ReminderTmp->Info, sizeof(NV_UI_Calendar_Reminder_t));
            UI_NV_Write_Req(NV_SECTION_UI_CALENDAR,
                            ReminderTmp->IndexInNV * sizeof(NV_UI_Calendar_Reminder_t),
                            sizeof(NV_UI_Calendar_Reminder_t), (UINT8 *)(&NvReminderInfo));

            Display_Calendar_Alarm_Postponed();

            g_CalendarMng.AlarmReminder = NULL;
            Alarm_Calendar_Alarm_Change_Ind(FALSE);
        }
        else
        {
            Display_Calendar_Reminder_Discarded();
        }
    }

    return(1);
}

/**
 * Process user key of Calendar option UI
 */
UINT8 Cale_Key_Proc_Lunar_Cale(lv_obj_t *obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    UINT32    Snd;
    hal_rtc_t tm = {};

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT:
            Nav_Back(ACT_ID_ANY);
            return(1);

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            return(1);

        case KEY_OK:
            Display_Calendar_Go_To_Date();
            return(1);

        case KEY_UP:
        case KEY_DOWN:
            tm.tm_year = g_CalendarMng.LunarDate->year;
            tm.tm_mon  = g_CalendarMng.LunarDate->month;
            tm.tm_mday = g_CalendarMng.LunarDate->day;

            Snd = UI_Time_to_Seconds(&tm);
            if (KEY_DOWN == Key_Val)
            {
                Snd += 24 * 60 * 60;
            }
            else
            {
                Snd -= 24 * 60 * 60;
            }

            UI_Seconds_to_Time(Snd, &tm);

            g_CalendarMng.LunarDate->year  = tm.tm_year;
            g_CalendarMng.LunarDate->month = tm.tm_mon;
            g_CalendarMng.LunarDate->day   = tm.tm_mday;

            UI_Cale_Show_Lunar_Info(g_CalendarMng.CurrentDesc);
            return(1);

        default:
            return(1);
        }     /* switch */
    }

    return(1);
} /* Cale_Key_Proc_Lunar_Cale */

/**
 * rel func for Add reminder of calendar option
 * param(in) Obj: lv_obj_t *Obj,lv_event_t event
 * return: void
 */
void Cale_Rel_Func_Add_Reminder(lv_obj_t *Obj,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    g_CalendarMng.Process = UI_CALE_PROCESS_ADD_REMINDER;
    Display_Calendar_Add_Reminder();
}

/**
 * rel func for view today of calendar option
 * param(in) Obj: lv_obj_t *Obj,lv_event_t event
 * return: void
 */
void Cale_Rel_Func_View_Today(lv_obj_t *Obj,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    g_CalendarMng.Process = UI_CALE_PROCESS_VIEW_TODAY;
    Display_Calendar_View_All();
}

/**
 * rel func for go to date of calendar option
 * param(in) lv_obj_t *Obj,lv_event_t event
 * return: void
 */
void Cale_Rel_Func_Go_To_Date(lv_obj_t *Obj,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    Display_Calendar_Go_To_Date();
}

/**
 * rel func for view all of calendar option
 * param(in) Obj: lv_obj_t *Obj,lv_event_t event
 * return: void
 */
void Cale_Rel_Func_View_All(lv_obj_t *Obj,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    g_CalendarMng.Process = UI_CALE_PROCESS_VIEW_ALL;
    Display_Calendar_View_All();
}

/**
 * rel func for Lunar calendar of calendar option
 * param(in) lv_obj_t *Obj,lv_event_t event
 * return: void
 */
void Cale_Rel_Func_Lunar_Cale(lv_obj_t *Obj,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    Setting_Phone_Setting_t Settings;

    Settings.ChangeMark = IF_SETTING_CHANGE_MARK_CURRENT_LANGUAGE;

    Setting_Get_Phone_Setting_Req(&Settings);

    if (SETTING_LANGUAGE_EN == Settings.CurrentLanguage)
    {
        Display_Calendar_For_Chinese();
    }
    else
    {
        Display_Calendar_Lunar_Cale();
    }
}

/**
 * rel func for Alarm on of Set alarm
 * param(in) lv_obj_t *Obj,lv_event_t event
 * return: void
 */
void Cale_Rel_Func_Alarm_On(lv_obj_t *Obj,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    if (UI_CALE_PROCESS_ADD_REMINDER == g_CalendarMng.Process)
    {
        Display_Calendar_Set_Time();
    }
    else // edit
    {
        Display_Calendar_Set_Date();
    }
}

/**
 * rel func for Alarm off of Set alarm
 * param(in) lv_obj_t *Obj,lv_event_t event
 * return: void
 */
void Cale_Rel_Func_Alarm_Off(lv_obj_t *Obj,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    // save reminder
    if (UI_CALE_PROCESS_ADD_REMINDER == g_CalendarMng.Process)
    {
        UI_Cale_Save_For_Add_Reminder(0xFF, 0xFF);
    }
    else
    {/*View all or View today process*/
        UI_Cale_Save_For_Edit_Reminder(0xFF, 0xFF);
    }
    Display_Calendar_Reminder_Added();
}

/**
 * rel func for Alarm off of Set alarm
 * param(in) lv_obj_t *Obj,lv_event_t event
 * return: void
 */
void Cale_Rel_Func_View_Option_Delete(lv_obj_t *Obj,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    Display_Calendar_Delete();
}

/**
 * rel func for Alarm off of Set alarm
 * param(in) lv_obj_t *Obj,lv_event_t event
 * return: void
 */
void Cale_Rel_Func_View_Option_Edit(lv_obj_t *Obj,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    // save reminder
    Display_Calendar_View_Edit();
}
